package com.shortlink.common.config;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.shortlink.common.base.Result;
import com.shortlink.common.base.errcode.BaseErrorCode;
import com.shortlink.common.constant.HeaderConstant;
import com.shortlink.common.exception.RemoteException;
import com.shortlink.common.user.UserContext;
import feign.Feign;
import feign.RequestInterceptor;
import feign.Response;
import feign.Util;
import feign.codec.DecodeException;
import feign.codec.Decoder;
import feign.codec.ErrorDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Type;

/**
 * openFeign 微服务调用传递用户信息配置
 *
 * @author wp
 */
@Slf4j
@Configuration
@EnableFeignClients("com.shortlink.*.remote")
@ConditionalOnClass(Feign.class)
public class OpenFeignConfiguration {
    @Bean
    public RequestInterceptor requestInterceptor() {
        return template -> {
            String username = UserContext.getUsername();
            Long userId = UserContext.getUserId();

            if (!ObjectUtil.isAllNotEmpty(userId, username)) {
                return;
            }

            template.header(HeaderConstant.USER_ID, userId.toString());
            template.header(HeaderConstant.USERNAME, username);

            String groupName = UserContext.getGroupName();
            if (groupName != null && !groupName.isEmpty()) {
                template.header(HeaderConstant.USER_GROUP_NAME, groupName);
            }

            Integer groupLevel = UserContext.getGroupLevel();
            if (groupLevel != null) {
                template.header(HeaderConstant.USER_GROUP_LEVEL, groupLevel.toString());
            }
        };
    }

    @Bean
    public ErrorDecoder errorDecoder() {
        return (String methodKey, Response response) -> {
            log.error("Feign调用异常 {}", response.status());
            throw new RemoteException(BaseErrorCode.SERVER_ERROR);
        };
    }

    @Bean
    public Decoder decoder() {
        return (Response response, Type type) -> {
            if (response.body() == null) {
                throw new DecodeException(response.status(), "没有返回有效的数据", response.request());
            }
            String bodyStr = Util.toString(response.body().asReader(Util.UTF_8));

            Result<?> result = JSONUtil.toBean(bodyStr, type, false);

            if (!result.isSuccess()) {
                throw new RemoteException(result.getMessage());
            }
            return result;
        };
    }
}
